package com.shiny.widgetsdk.network;

import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import org.json.JSONObject;

import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 封装Okhttp工具类
 * 主要将OkHttp3工具类进行封装，用于对数据的传输，包括spring、JSON、img、表单等数据的提交与获取
 * 1、支持SPDY，共享同一个Socket来处理同一个服务器的所有请求；
 * 2、如果SPDY不可用。则通过连接池来减少请求延时；
 * 3、无缝的支持GZIP来减少数据流量；
 * 4、缓存响应数据来减少重复的网络请求。
 * 5：拦截器 1、创建一系列的拦截器，并将其放入一个拦截器list中 2、创建一个拦截器链RealInterceptorChain，并执行拦截器链的proceed方法
 * RetryAndFollowUpInterceptor:
 * 1、创建StreamAllocation对象
 * 2、调用RealInterceptorChain.proceed(...)进行网络请求
 * 3、根据异常结果或者响应结果判断是否要进行重新请求
 * 4、调用下一个拦截器，对response进行处理，返回给上一个拦截器。
 *
 * BridgeInterceptor:
 * 1、是负责将用户构建的一个request请求转化为能够进行网络访问的请求
 * 2、将这个符合网络请求的request进行网络请求
 * 3、将网络请求回来的响应response转化为用户可用的response。
 * CacheInterceptor：
 * ConnectInterceptor：
 * 1、ConnectInterrceptor获取Interceptor传过来的StreamAllocation，StreamAllocation.newStream()；
 * 2、将刚才创建的用于网络IO的RealConnection的对象，以及对于与服务器交互最为关键的HttpCOdec等对象传递给后面的拦截器
 * ConnectPools:
 * 1、弄一个RealConnection对象
 * 2、选择不同的链接方式（socket链接或者http链接）
 * 3、CallServerInterceptor
 * CallServerInterceptor：
 * 1、产生一个StreamAllocation对象
 * 2、StreamAllocation对象的弱引用添加到RealConnection对象的allocations集合
 * 3、从连接池中获取
 */
public class CommonOkHttpClient {
    private final static String TAG = "OKHttpManager";

    private OkHttpClient client = null;
    private Handler handler;

    //提交json数据
    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");

    //提交字符串数据
    private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown;charset=utf-8");

    private CommonOkHttpClient(){
        client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
        handler = new Handler(Looper.getMainLooper());
    }

    private enum Singleton{
        INSTANCE;
        private CommonOkHttpClient okHttpManager;
        Singleton(){
            okHttpManager = new CommonOkHttpClient();
        }
        public CommonOkHttpClient getOkHttp(){
            return okHttpManager;
        }
    }

    public static CommonOkHttpClient getInstance(){
        return Singleton.INSTANCE.getOkHttp();
    }

    /**
     * @param jsonValue
     * @param callBack
     * @exception请求返回JSon字符串
     */
    private void onSuccessJsonStringMethod(final String jsonValue, final StringResponse callBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        callBack.onResponse(jsonValue);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * @param data
     * @param callback
     * @exception返回响应的对象是一组字节数组
     */
    private void onSuccessByteMethod(final byte[] data, final ByteArrayResponse callback){
        handler.post(new Runnable() {
            @Override
            public void run() {
                if ( null != callback ) {
                    try {
                        callback.onResponse(data);
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * @param bitmap
     * @param callback
     * exception:返回响应的对象是bitmap对象
     */
    private void onSuccessImgMethod(final Bitmap bitmap, final BitmapResponse callback) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (null != callback) {
                    try{
                        callback.onResponse(bitmap);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * @param jsonValue
     * @param callback
     * @exception:返回响应的对象是JSon对象
     */
    private void onSuccessJSonMethod(final String jsonValue, final JSonResponse callback) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (null != callback) {
                    try{
                        callback.onResponse(new JSONObject(jsonValue));
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * @param url
     * @return:同步请求(会阻塞Ui线程）
     */
    public String syncGetByUrl(final String url) {
//        final Request request = new Request.Builder().url(url).build();
//        Response response = null;
//        try{
//            response = client.newCall(request).execute(); //executor用于同步请求数据
//            if ( response.isSuccessful() ) {
//                return response.body().string();
//            }
//        }catch (Exception e) {
//            e.printStackTrace();
//        }
        return null;
    }

    /**
     * @param url
     * @param callback
     * @exception:异步请求返回JSon对象
     */
    public void asyncJsonStringByUrl(String url, final StringResponse callback) {
//        final Request request = new Request.Builder().url(url).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if (  null != response && response.isSuccessful() ) {
//                    onSuccessJsonStringMethod(response.body().string(),callback);
//                }
//            }
//        });
    }

    /**
     * @param url
     * @param callback
     * @exception:异步请求返回字符串
     */
    public void asyncGetByteByUrl(String url, final ByteArrayResponse callback ) {
//        final Request request = new Request.Builder().url(url).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if ( null != response && response.isSuccessful() ) {
//                    onSuccessByteMethod(response.body().bytes(),callback);
//                }
//            }
//        });
    }

    /**
     * @param url
     * @param callback
     * @exception:异步请求返回Bitmap对象
     */
    public void asyncDownLoadBitmapByUrl(String url,final BitmapResponse callback){
//        final Request request = new Request.Builder().url(url).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
////                if (null != response && response.isSuccessful() ) {
////                    byte[] data = response.body().bytes();
////                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
////                    onSuccessImgMethod(bitmap,callback);
////                }
//            }
//        });
    }

    /**
     * @param url
     * @param callback
     * @exception:异步请求返回JSon对象
     */
    public void asyncJSonObjectByUrl(String url, final JSonResponse callback){
//        final Request request = new Request.Builder().url(url).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if (null != response && response.isSuccessful() ) {
//                   // onSuccessJSonMethod(response.body().string(),callback);
//                }
//            }
//        });
    }

    /**
     * @param url
     * @param param
     * @param callback
     * @exception:模拟表单提交
     * POST请求跟Get基本相同，需要增加RequestBody来存储请求的参数信息；在Request.Builder中增加post(RequestBody)调用
     */
    public void sendComplexForm(String url, Map<String, String> param, final JSonResponse callback) {
        //FormBody.Builder form_build = new FormBody.Builder(); //表单对象。包含以input开始的对象，模拟一个表单操作，以HTML表单为主

        //如果键值对不为空，且值不为空
//        if( null != param && !param.isEmpty() ) {
//            for( Map.Entry<String,String> entry : param.entrySet()) {
//                form_build.add(entry.getKey(),entry.getValue());
//            }
//        }
//        RequestBody requestBody = form_build.build();
//        //采用post的方式进行提交
//        Request request = new Request.Builder().url(url).post(requestBody).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                if( null != response && response.isSuccessful() ) {
//                  //  onSuccessJSonMethod(response.body().string(),callback);
//                }
//            }
//        });
    }

    /**
     * @param url
     * @param callback
     * @exception:向服务器提交String请求
     */
    public void sendStringByPost(String url, String content, final JSonResponse callback){
//        final Request request = new Request.Builder().url(url).post(RequestBody.create(MEDIA_TYPE_MARKDOWN,content)).build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                e.printStackTrace();
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//
//            }
//        });
    }

    public interface StringResponse{
        void onResponse(String result);
    }

    public interface ByteArrayResponse{
        void onResponse(byte[] result);
    }

    public interface BitmapResponse{
        void onResponse(Bitmap bitmap);
    }

    public interface JSonResponse{
        void onResponse(JSONObject jsonObject);
    }

}
